package cn.admin.remoting.impl;

import cn.admin.remoting.IOEventListener;
import cn.admin.remoting.RequestProcessor;
import cn.admin.remoting.Server;
import cn.admin.remoting.ServerManager;
import cn.admin.remoting.util.LoggerInit;
import cn.admin.remoting.util.ResourceInvalidException;
import cn.admin.remoting.util.SharedResourcesInit;
import cn.admin.remoting.util.UnsafeCast;

import java.util.List;
import java.util.concurrent.ExecutionException;

public class DefaultServerManager implements ServerManager {

    private ServerRepo serverRepo = new ServerRepo();

    @Override
    public Server getServer(String bindIp, int port,
                            List<IOEventListener> listeners,
                            List<RequestProcessor<?>> processors) {
        String serverKey = getServerKey(bindIp,port);
        Object[] attach = new Object[]{listeners,processors};
        Server server = null;

        try {
            server = serverRepo.getResource(serverKey,attach);
            System.out.println(server.getClass());
        } catch (ResourceInvalidException | InterruptedException | ExecutionException e) {
            LoggerInit.LOGGER.warn("取server[" + serverKey + "]时出现异常:" + e.getMessage(),e);
        }
        return server;
    }

    private static String getServerKey(String bindIp,int port) {
        String ip = null == bindIp ? "" : bindIp;
        return ip + "#" + port;
    }

    private static Object[] parseServerKey(String key) {
        String[] tokens = key.split("#");
        return new Object[]{tokens[0],Integer.parseInt(tokens[1])};
    }

    private static class ServerRepo extends SharedResourcesInit<Server> {

        @Override
        protected boolean isSingletonResource() {
            return false;
        }

        @Override
        protected void validate(Server resource) throws ResourceInvalidException {
            if (((DefaultServer)resource).isStopped()) {
                throw new ResourceInvalidException("server closed");
            }
        }

        protected Server keyedInitResource(String key,Object attachment) throws Exception {
            Object[] tmp = parseServerKey(key);
            String bindIp = UnsafeCast.cast(tmp[0]);
            int port = (int) tmp[1];
            Server server = new DefaultServer(bindIp,port);
            if (attachment != null ) {
                Object[] attach = (Object[]) attachment;
                if (attach[0] != null) {
                    List<IOEventListener> processors = UnsafeCast.cast(attach[0]);
                    for (IOEventListener listener : processors) {
                        server.addListener(listener);
                    }
                }
                if (attach[1] != null) {
                    List<RequestProcessor<?>> processors = UnsafeCast.cast(attach[1]);
                    for (RequestProcessor<?> processor : processors) {
                        server.registerProcessor(processor);
                    }
                }
            }
            return server;
        }
    }
}
